package scparser.factory.sceneFactory;

import java.io.BufferedReader; 
import java.io.IOException;
import javax.vecmath.Point3d;
import lib.common.Constants;
import model.Color;
import model.Shader;
import model.Spec;
import model.Shader.Type;

import raycast.Scene;
import scparser.ParserHelper;
import scparser.factory.primitiveFactory.PrimitiveFactoryException;

public class SceneShaderFactory extends SceneFactory {
	private Color color;
	private Color diff;
	private Spec spec;
	private Shader.Type type;
	
	public SceneShaderFactory(Scene scene) {
		super.scene = scene;
	}

	@Override
	public Object create(BufferedReader br) throws PrimitiveFactoryException {
		String line = null;
		String typeString = null;
		
		try {
			while ((line = br.readLine()).contains(Constants.S_CLOSE) == false) {
				line = line.trim();
				if (line.startsWith("type")) {
					typeString = ParserHelper.takeString(line, "type");
					this.type = findType(typeString);
					if (this.type == null) {
						throw new PrimitiveFactoryException("invalid shader type");
					}
				}
				
				if (line.startsWith("diff")) {
					this.diff = getColor(br);
					if (diff == null) {
						throw new PrimitiveFactoryException("in shader object, diff option missing");
					}
				}
				
				if (line.startsWith("spec")) {
					this.spec = getSpec(br);
					if (spec == null) {
						throw new PrimitiveFactoryException("in shader object, spec option missing");
					}
				}
				
				if (line.startsWith("color")) {
					this.color = getColor(br);
					if (color == null) {
						throw new PrimitiveFactoryException("in shader object, color option missing");
					}
				}
				
				if (line.startsWith("name")) {
					super.name = ParserHelper.takeString(line, "name");
				}
			}
		} catch (IOException e) {
			throw new PrimitiveFactoryException(e.getMessage());
		}
		
		
		Shader ret = new Shader(super.name, this.color, this.diff, this.spec, this.type);
		if (super.scene.getShaders().contains(ret)) {
			throw new PrimitiveFactoryException("shader already exists");
		}
		
		return ret;
	}

	private Type findType(String typeString) {
		for (Shader.Type t: Shader.Type.values()) {
			if (t.toString().equals(typeString)) {
				return t;
			}
		}
		return null;
	}

	private Spec getSpec(BufferedReader br) throws PrimitiveFactoryException {
		String line = null;				
		try {
			while ((line = br.readLine()) != null) {
				if (!line.trim().equals("")) {
					line = line.replaceAll("{", "");
					line = line.replaceAll("}", "");
					String[] values = line.split(" ");
					String type = values[1];
					if (type == null || type.equals("")) {
						throw new PrimitiveFactoryException("shader type option missing");
					}
					Point3d p;
					p = ParserHelper.takePoint(line, "\"sRGB nonlinear\"");
					
					return new Spec(type, p, Double.parseDouble(values[values.length-1]));
				}
			}
		} catch (IOException e) {
			throw new PrimitiveFactoryException(e.getMessage());
		}
		return null;
	}

	private Color getColor(BufferedReader br) throws PrimitiveFactoryException{
		String line = null;				
		try {
			while ((line = br.readLine()) != null) {
				if (!line.trim().equals("")) {
					line = line.replaceAll("{", "");
					line = line.replaceAll("}", "");
					String[] values = line.split(" ");
					String type = values[1];
					if (type == null || type.equals("")) {
						throw new PrimitiveFactoryException("shader type option missing");
					}
					Point3d p;
					p = ParserHelper.takePoint(line, "\"sRGB nonlinear\"");
					
					return new Color(type, p);
				}
			}
		} catch (IOException e) {
			throw new PrimitiveFactoryException(e.getMessage());
		}
		
		return null;
	}

}
